#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>

// 测试用例1: 基础对齐
#pragma pack(push, 2)
struct TestCase1
{
    char a;
    int b;
    double c;
};
#pragma pack(pop)

// 测试用例2：混合类型+数组
#pragma pack(push, 4)
struct TestCase2
{
    unsigned char a;
    unsigned int b;
    unsigned short c[3];
};
#pragma pack(pop)

// 测试用例3：自然对齐

struct TestCase3
{
    double a;
    char b;
    struct TESTCase3 *c;
};

// 测试用例4：显式对齐
struct __attribute__((aligned(16))) TestCase4
{
    int a;
    double b;
};

// 测试用例5: 浮点数数组对齐
#pragma pack(push, 4)
struct TestCase5
{
    float positions[3]; // 对应 @CStruct.F32A(3)
    unsigned char flag; // 对应 @CStruct.U8()
};
#pragma pack(pop)

// 测试用例6: 混合长度字符串
#pragma pack(push, 1)
struct TestCase6
{
    char name[8];     // 对应 @CStruct.Str(8)
    char address[16]; // 对应 @CStruct.Str(16)
};
#pragma pack(pop)

// 测试用例7: 复杂嵌套结构
struct TestCase7_Inner
{
    unsigned short x; // 对应 @CStruct.U16()
    unsigned short y; // 对应 @CStruct.U16()
};

#pragma pack(push, 4)
struct TestCase7
{
    unsigned int id;              // 对应 @CStruct.U32()
    struct TestCase7_Inner point; // 对应 @CStruct.Struct(Inner)
    unsigned char data[5];        // 对应 @CStruct.U8A(5)
};
#pragma pack(pop)

// 测试用例8: 最大对齐边界
struct __attribute__((aligned(128))) TestCase8
{
    unsigned char a; // 对应 @CStruct.U8()
    unsigned long b; // 对应 @CStruct.U64()
};

// 测试用例9
#pragma pack(push, 1)
struct TestCase9
{
    unsigned char flag;
    struct
    {
        unsigned char b1 : 1;
        unsigned char b2 : 1;
        unsigned char b3 : 1;
        unsigned char b4 : 1;
        unsigned char b5 : 1;
        unsigned char b6 : 1;
        unsigned char b7 : 1;
        unsigned char b8 : 1;
    } bits[3]; // 3字节位域
};
#pragma pack(pop)

// 测试用例10
#pragma pack(push, 1)
struct TestCase10
{
    unsigned char a;
    unsigned char b;
    unsigned char c;
};
#pragma pack(pop)

// 测试用例11
#pragma pack(push, 4)
struct TestCase11
{
    unsigned short arr[4];
    float f;
    unsigned char bytes[3];
};
#pragma pack(pop)

// 测试用例12
#pragma GCC diagnostic ignored "-Wpragmas"
#pragma pack(push, 64)
struct TestCase12
{
    unsigned char a;
    unsigned long long b;
};
#pragma pack(pop)

// 测试用例13
struct TestCase13_Item
{
    unsigned short id;
    unsigned char flag;
};

struct TestCase13
{
    struct TestCase13_Item items[3];
};

// 测试用例14
struct TestCase14_InnerA
{
    uint16_t x;
};

#pragma pack(push, 2)
struct TestCase14_InnerB
{
    struct TestCase14_InnerA a;
    uint8_t y;
};
#pragma pack(pop)

struct __attribute__((aligned(8))) TestCase14
{
    struct TestCase14_InnerB b;
    double z;
};

// 测试用例15
#pragma pack(push, 2)
struct __attribute__((aligned(16))) TestCase15
{
    uint8_t a;
    uint32_t b;
    uint64_t c;
};
#pragma pack(pop)

// 测试用例16
#pragma pack(push, 1)
struct TestCase16
{
    char buffer[256];
};
#pragma pack(pop)

// 测试用例17
#pragma pack(push, 4)
struct TestCase17
{
    int8_t a;
    uint32_t b;
    int64_t c;
};
#pragma pack(pop)

// 测试用例18
struct TestCase18_Item
{
    uint16_t id;
    uint8_t status;
};

#pragma pack(push, 8)
struct TestCase18
{
    struct TestCase18_Item items[4];
    uint64_t timestamp;
};
#pragma pack(pop)

// 测试用例19
#pragma pack(push, 8)
struct TestCase19
{
    uint32_t size;
    uint64_t pointer;
};
#pragma pack(pop)

// 测试用例20
struct __attribute__((aligned(32))) TestCase20
{
    unsigned char padding[31];
    uint64_t marker;
};

struct TestBasic
{
    uint8_t a;  // offset 0
    uint32_t b; // offset 4 (1+3 padding)
    double c;   // offset 8
};

struct __attribute__((aligned(4))) TestWeakAlign
{
    char b;
    double a; // 自然对齐8，显式对齐4无效
};
int main(int argc, char *argv[])
{
    if (argc < 2)
    {
        printf("Usage: %s <test_case_number>\n", argv[0]);
        return 1;
    }

    switch (atoi(argv[1]))
    {
    case 1:
    {
        printf("a:%zu b:%zu c:%zu size:%zu",
               offsetof(struct TestCase1, a),
               offsetof(struct TestCase1, b),
               offsetof(struct TestCase1, c),
               sizeof(struct TestCase1));
        break;
    }
    case 2:
    {
        struct TestCase2 s;
        printf("a:%ld b:%ld c:%ld size:%ld",
               offsetof(struct TestCase2, a),
               offsetof(struct TestCase2, b),
               offsetof(struct TestCase2, c),
               sizeof(s));
        break;
    }
    case 3:
    {
        struct TestCase3 s;
        printf("a:%ld b:%ld c:%ld size:%ld",
               offsetof(struct TestCase3, a),
               offsetof(struct TestCase3, b),
               offsetof(struct TestCase3, c),
               sizeof(s));
        break;
    }
    case 4:
    {
        struct TestCase4 s;
        printf("a:%ld b:%ld size:%ld",
               offsetof(struct TestCase4, a),
               offsetof(struct TestCase4, b),
               sizeof(s));
        break;
    }
    case 5:
    {
        struct TestCase5 s;
        printf("positions:%zu flag:%zu size:%zu",
               offsetof(struct TestCase5, positions),
               offsetof(struct TestCase5, flag),
               sizeof(struct TestCase5));
        break;
    }
    case 6:
    {
        struct TestCase6 s;
        printf("name:%zu address:%zu size:%zu",
               offsetof(struct TestCase6, name),
               offsetof(struct TestCase6, address),
               sizeof(struct TestCase6));
        break;
    }
    case 7:
    {
        struct TestCase7 s;
        printf("id:%zu point:%zu data:%zu size:%zu",
               offsetof(struct TestCase7, id),
               offsetof(struct TestCase7, point),
               offsetof(struct TestCase7, data),
               sizeof(struct TestCase7));
        break;
    }
    case 8:
    {
        struct TestCase8 s;
        printf("a:%zu b:%zu size:%zu",
               offsetof(struct TestCase8, a),
               offsetof(struct TestCase8, b),
               sizeof(struct TestCase8));
        break;
    }
    case 9:
    {
        struct TestCase9 s;
        printf("flag:%zu bits:%zu size:%zu",
               offsetof(struct TestCase9, flag),
               offsetof(struct TestCase9, bits),
               sizeof(struct TestCase9));
        break;
    }
    case 10:
    {
        struct TestCase10 s;
        printf("a:%zu b:%zu c:%zu size:%zu",
               offsetof(struct TestCase10, a),
               offsetof(struct TestCase10, b),
               offsetof(struct TestCase10, c),
               sizeof(struct TestCase10));
        break;
    }
    case 11:
    {
        struct TestCase11 s;
        printf("arr:%zu f:%zu bytes:%zu size:%zu",
               offsetof(struct TestCase11, arr),
               offsetof(struct TestCase11, f),
               offsetof(struct TestCase11, bytes),
               sizeof(struct TestCase11));
        break;
    }
    case 12:
    {
        struct TestCase12 s;
        printf("a:%zu b:%zu size:%zu",
               offsetof(struct TestCase12, a),
               offsetof(struct TestCase12, b),
               sizeof(struct TestCase12));
        break;
    }
    case 13:
    {
        struct TestCase13 s;
        printf("items:%zu size:%zu",
               offsetof(struct TestCase13, items),
               sizeof(struct TestCase13));
        break;
    }
    case 14:
    {
        struct TestCase14 s;
        printf("b:%zu z:%zu size:%zu",
               offsetof(struct TestCase14, b),
               offsetof(struct TestCase14, z),
               sizeof(struct TestCase14));
        break;
    }
    case 15:
    {
        struct TestCase15 s;
        printf("a:%zu b:%zu c:%zu size:%zu",
               offsetof(struct TestCase15, a),
               offsetof(struct TestCase15, b),
               offsetof(struct TestCase15, c),
               sizeof(struct TestCase15));
        break;
    }
    case 16:
    {
        struct TestCase16 s;
        printf("buffer:%zu size:%zu",
               offsetof(struct TestCase16, buffer),
               sizeof(struct TestCase16));
        break;
    }
    case 17:
    {
        struct TestCase17 s;
        printf("a:%zu b:%zu c:%zu size:%zu",
               offsetof(struct TestCase17, a),
               offsetof(struct TestCase17, b),
               offsetof(struct TestCase17, c),
               sizeof(struct TestCase17));
        break;
    }
    case 18:
    {
        struct TestCase18 s;
        printf("items:%zu timestamp:%zu size:%zu",
               offsetof(struct TestCase18, items),
               offsetof(struct TestCase18, timestamp),
               sizeof(struct TestCase18));
        break;
    }
    case 19:
    {
        struct TestCase19 s;
        printf("size:%zu pointer:%zu size:%zu",
               offsetof(struct TestCase19, size),
               offsetof(struct TestCase19, pointer),
               sizeof(struct TestCase19));
        break;
    }
    case 20:
    {
        struct TestCase20 s;
        printf("padding:%zu marker:%zu size:%zu",
               offsetof(struct TestCase20, padding),
               offsetof(struct TestCase20, marker),
               sizeof(struct TestCase20));
        break;
    }
    case 21:
    {
        printf("a:%lu b:%lu\n c:%lu size:%lu",
               offsetof(struct TestBasic, a),
               offsetof(struct TestBasic, b),
               offsetof(struct TestBasic, c),
               sizeof(struct TestBasic));
        return 0;
    }
    case 22:
    {
        printf("size=%lu\nalign=%lu",
               sizeof(struct TestWeakAlign),
               _Alignof(struct TestWeakAlign));
        return 0;
    }
    case 23:
    {
        struct __attribute__((aligned(16))) TestStrongAlign
        {
            int a;
        };
        printf("size=%lu\nalign=%lu",
               sizeof(struct TestStrongAlign),
               _Alignof(struct TestStrongAlign));
        return 0;
    }
    case 24:
    {
        struct TestWithArray
        {
            unsigned char arr[3]; // offset 0
            int b;                // offset 4 (3+1 padding)
        };
        printf("b=%lu\nsize=%lu",
               offsetof(struct TestWithArray, b),
               sizeof(struct TestWithArray));
        return 0;
    }
    case 25:
    {
        struct Nested
        {
            uint16_t a; // offset 0
        }; // size=2, align=2

        struct TestNested
        {
            struct Nested nested; // offset 0
            int b;                // offset 4 (2+2 padding)
        };
        printf("b=%lu\nsize=%lu",
               offsetof(struct TestNested, b),
               sizeof(struct TestNested));
        return 0;
    }
    case 26:
    {
        struct TestStrongAlign
        {
            int a;
        } __attribute__((aligned(16))); // 显式对齐16

#pragma pack(push, 4)
        struct TestComplex
        {
            uint8_t a;                // offset 0
            uint64_t b;               // offset 4（受 pack(4) 限制）
            struct TestStrongAlign c; // offset max(4+8=12, 16) → 16
        };
#pragma pack(pop)
        printf("strongAlign=%lu\nsize=%lu",
               offsetof(struct TestComplex, c),
               sizeof(struct TestComplex));
        return 0;
    }
    case 27:
    {
        struct TestTrailingPadding
        {
            int a;  // offset 0
            char b; // offset 4
        };
        printf("size=%lu", sizeof(struct TestTrailingPadding));
        return 0;
    }
    case 28:
    {
        struct A
        {
            int a;
        };
        struct B
        {
            char b;
            struct A __attribute__((aligned(16))) c;
            char d;
        };
        printf("size=%lu c=%lu d=%lu", sizeof(struct B), offsetof(struct B, c), offsetof(struct B, d));
        return 0;
    }
    case 29:
    {
        struct GrandParent
        {
            uint8_t a;
        };
        struct Parent
        {
            uint8_t a;
            uint16_t b;
        };
        struct Child
        {
            uint8_t a;
            uint16_t b;
            uint32_t c;
        };
        printf("a=%lu\nb=%lu\nc=%lu\nsize=%lu",
               offsetof(struct Child, a),
               offsetof(struct Child, b),
               offsetof(struct Child, c),
               sizeof(struct Child));
        return 0;
    }
    case 30:
    {
#pragma pack(push, 4)
        typedef struct A
        {
            uint16_t a;
        } StructA;
#pragma pack(pop)
        typedef struct B
        {
            struct A elements[3];
        } StructB;
        printf("size=%lu\nelements=%lu", sizeof(struct B), sizeof(StructA[3]));
        return 0;
    }
    case 31:
    {

        typedef struct __attribute__((aligned(128)))
        {
            uint8_t a;
            uint64_t b;
        } StructA;
        printf("size=%lu", sizeof(StructA));
        return 0;
    }
    case 32:
    {
        #pragma pack(push, 1)
        typedef struct __attribute__((aligned(128)))
        {
            uint8_t a[63];
            double data;
        } StructA;
        #pragma pack(pop)
        printf("data=%lu size=%lu", offsetof(StructA, data), sizeof(StructA));
        return 0;
    }
    case 33:
    {
        #pragma pack(push, 8)
        typedef struct __attribute__((aligned(16))){
            uint32_t a;
        }StructA;
        #pragma pack(pop)
        #pragma pack(push, 4)
        typedef struct{
            StructA a;
            double b;
        }StructB;
        #pragma pack(pop)
        printf("b=%lu size=%lu", offsetof(StructB, b), sizeof(StructB));
        return 0;
    }
    default:
        printf("Invalid test case");
        return 1;
    }
    return 0;
}